package com.aoip.telemetry.telemetry.receive.call.controller;

import com.aoip.telemetry.telemetry.core.entity.AjaxResult;
import com.aoip.telemetry.telemetry.core.redis.RedisCache;
import com.aoip.telemetry.telemetry.entity.constant.TelemetryConstants;
import com.aoip.telemetry.telemetry.entity.enums.CacheKeyEnum;
import com.aoip.telemetry.telemetry.entity.equipment.QuerySetOrderEntity;
import com.aoip.telemetry.telemetry.receive.session.Session;
import com.aoip.telemetry.telemetry.receive.session.SessionFactory;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.socket.DatagramPacket;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * 测站召测（查询、设置指令发送）
 *
 * @author chenbai
 * @version 1.0
 * @date 2022/2/21 10:42
 */
@RestController
@Slf4j
public class QuerySetOrderController {

    @Resource
    private RedisCache redisCache;
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmss");
    /**
     * 指令发送
     *
     * @param entity 查询设置指令
     * @return com.aoip.telemetry.telemetry.core.entity.AjaxResult
     * @author chenbai
     * @date 2022/2/21
     **/
    @PostMapping("/v1/POST/order/call")
    public AjaxResult orderCall(@RequestBody QuerySetOrderEntity entity) {
        String stCode = entity.getStCode();
        String msg = entity.getAllMsg();
        redisCache.setCacheObject(CacheKeyEnum.ORDER_NO_SEND_STORE_HOUSE + ":" + stCode + ":" + entity.getOrderBaseId(), entity);
        return AjaxResult.success("指令设置成功，收到测站心跳报文后将自动发送，指令信息为：" + msg);
//        if (channel == null) {
//            redisCache.setCacheObject(CacheKeyEnum.ORDER_NO_SEND_STORE_HOUSE + ":" + stCode + ":" + msg, entity);
//            return AjaxResult.error("设备不在线，指令将在设备上线后自动发送");
//        }
//        return send(msg, msgType, session, channel);
    }

    /**
     * 站点上线后自动发送
     *
     * @param stCode 测站编码
     * @author chenbai
     * @date 2022/7/11
     **/
    public void autoSend(String stCode) {
        Collection<String> keys = redisCache.keys(CacheKeyEnum.ORDER_NO_SEND_STORE_HOUSE + ":" + stCode + ":*");
        if (keys != null && keys.size() > 0) {
            keys.forEach(key -> {
                QuerySetOrderEntity entity = redisCache.getCacheObject(key);
                String msg = entity.getAllMsg();
                if (msg.indexOf("yyMMddHHmmss") > 0) {
                    String nowTime = DATE_TIME_FORMATTER.format(LocalDateTime.now());
                    msg = msg.replace("yyMMddHHmmss", nowTime);
                }
                String msgType = entity.getMsgType();
                Session session = SessionFactory.getSession();
                Channel channel = session.getChannel(stCode);
                log.error("测站编码：{};下发报文编码格式：{};下发完整报文：{}", stCode, msgType, msg);
                send(msg, msgType, session, channel);
//                AjaxResult result = orderCall(entity);
//                Object o = result.get(AjaxResult.CODE_TAG);
//                if (o.equals(HttpStatus.SUCCESS)) {
//                    redisCache.deleteObject(key);
//                }
                redisCache.deleteObject(key);
            });
        }
    }

    private static AjaxResult send(String msg, String msgType, Session session, Channel channel) {
        Object protocolCommunicate = session.getAttribute(channel, "protocolCommunicate");
        InetSocketAddress inSocket = (InetSocketAddress) session.getAttribute(channel, "inSocket");
        ByteBuf heapBuffer = channel.alloc().heapBuffer();
        log.error("通讯方式：{}", protocolCommunicate);
        Object send;
        if (TelemetryConstants.ASCII.equals(msgType)) {
            if (TelemetryConstants.TCP.equals(protocolCommunicate)) {
                heapBuffer.writeBytes(msg.getBytes());
                log.error("1111");
                send = heapBuffer;
            } else {
                heapBuffer.writeBytes(msg.getBytes());
                send = new DatagramPacket(heapBuffer, inSocket);
                log.error("2222");
            }
        } else {
            try {
                byte[] bytes = Hex.decodeHex(msg.toCharArray());
                if (TelemetryConstants.TCP.equals(protocolCommunicate)) {
                    heapBuffer.writeBytes(bytes);
                    send = heapBuffer;
                    log.error("333");
                } else {
                    heapBuffer.writeBytes(bytes);
                    send = new DatagramPacket(heapBuffer, inSocket);
                    log.error("444");
                }
            } catch (DecoderException e) {
                e.printStackTrace();
                log.error("555");
                return AjaxResult.error("编码转换失败！" + e.getMessage());
            }
        }
        log.error("6666");
        ChannelFuture channelFuture = channel.writeAndFlush(send);
        AtomicInteger i = new AtomicInteger(0);
        channelFuture.addListener((ChannelFutureListener) future -> {
            if (future.isSuccess()) {
                i.getAndAdd(1);
                log.error("指令发送成功");
            } else {
                log.error("指令发送失败");
            }
        });
        if (i.get() > 0) {
            return AjaxResult.success("指令发送成功");
        } else {
            return AjaxResult.success("指令发送失败");
        }

    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        String str = "ST 6075102044 PW 371800 TT 230627222427 CN 1482 koNN";
        byte[] bytesU8 = str.getBytes(StandardCharsets.UTF_8);
        byte[] bytesIso = str.getBytes(StandardCharsets.ISO_8859_1);
        byte[] strBytesGbk = str.getBytes("gbk");

        System.out.println(new String(bytesU8));
        System.out.println(new String(bytesIso));
        System.out.println(new String(strBytesGbk));

    }
}
